package com.tansun.easycare.rule.ruletest.service.impl;
/**
 * Created by Chenbaichuan on 2017/9/23 19:45
 **/

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tansun.easycare.rule.common.service.DataBomService;
import com.tansun.easycare.rule.common.service.impl.RuleBaseServiceImpl;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.ruleexcute.service.RuleExcuteService;
import com.tansun.easycare.rule.rulelog.entity.RuleLogs;
import com.tansun.easycare.rule.rulelog.service.RuleLogsService;
import com.tansun.easycare.rule.ruletest.dao.ContrastTestDao;
import com.tansun.easycare.rule.ruletest.dao.RuleTestDao;
import com.tansun.easycare.rule.ruletest.entity.RuleResp;
import com.tansun.easycare.rule.ruletest.entity.RuleTest;
import com.tansun.easycare.rule.ruletest.entity.RuleTestdata;
import com.tansun.easycare.rule.ruletest.model.ExcuteData;
import com.tansun.easycare.rule.ruletest.service.ContrastTestService;
import com.tansun.easycare.rule.ruletest.service.RuleRequestService;
import com.tansun.easycare.rule.ruletest.service.RuleResponseService;
import com.tansun.easycare.rule.ruletest.service.RuleTestItemService;
import com.tansun.easycare.rule.ruletest.service.RuleTestService;
import com.tansun.easycare.rule.ruletest.service.RuleTestdataService;
import com.tansun.rule.utils.LoggerManager;
//import com.tansun.ruledata.service.RuleLogService;

/**
 * @author chenbaichuan
 * @className ContrastTestServiceImpl
 * @desc
 * @created 2017/9/23 19:45
 **/
@Service
public class ContrastTestServiceImpl extends RuleBaseServiceImpl<RuleTestDao, RuleTest> implements
        ContrastTestService {
    @Autowired
    RuleExcuteService ruleExcuteService;
    @Autowired
    RuleTestService ruleTestService;
    @Autowired
    ContrastTestDao contrastTestDao;
    @Autowired
    RuleResponseService ruleResponseService;
    @Autowired
    DataBomService dataBomService;
    @Autowired
    RuleTestItemService ruleTestItemService;
    @Autowired
    RuleRequestService ruleRequestService;
    @Autowired
    RuleLogsService ruleLogsService;
    @Autowired
    RuleTestdataService ruleTestdataService;
//    @Autowired
//    RuleLogService ruleLogService;
    //单任务最大数据量
    private static final int TASK_DATA_NUM = 50;
    //对比测试类型
    private static final String CONTRASTTEST_TYPE = "2";


  

    /**
     * 执行对比测试
     *
     * @param excuteData  测试数据
     * @param projectCode 项目编号
     */
    public int excuteTest(String testModelId) throws BizException, ExecutionException, InterruptedException {
        RuleTest ruleTest = ruleTestService.get(testModelId);
        ExcuteData excuteData = new ExcuteData();
        excuteData.setTestId(ruleTest.getId());
        excuteData.setTestRuleCode(ruleTest.getModelCode());
        excuteData.setTestExcuteVersion(ruleTest.getVersion());
        RuleTestdata condition = new RuleTestdata();
        condition.setRelationId(testModelId);
        List<RuleTestdata> executeData = this.ruleTestdataService.findList(condition);
        for (RuleTestdata ruleTestdata : executeData) {
        	excuteData.getTxParamList().add(ruleTestdata.getRuleParam());
		}
        //	并行任务
	    ForkJoinPool forkJoinPool = new ForkJoinPool();
	    List<Integer> list = new ArrayList<Integer>();
	    TestParallelTask task = new TestParallelTask(excuteData, ruleTest.getProjectCode(), ruleTest.getId(),list);
	    forkJoinPool.invoke(task);
	    ruleTest.setStatus("2");
	    ruleTestService.save(ruleTest);
	    int count = 0;
	    for(Integer i : task.list) {
	    	count+=i;
	    }
	    return count;
    }

    

    /**
     * 对比测试保存或更新
     */
    @Override
    public void saveOrUpdate(RuleTest ruleTest) throws BizException {
        //名称重复
        RuleTest entity = new RuleTest();
        entity.setTestType(CONTRASTTEST_TYPE);
        entity.setProjectCode(ruleTest.getProjectCode());
        entity.setTestName(ruleTest.getTestName());
        List<RuleTest> ruleTestList = ruleTestService.findList(entity);
        if(ruleTestList.size()>0) {
        	 throw new BizException("", "测试实例名称重复");
        }
        try {
        	ruleTestService.save(ruleTest);
        	RuleLogs condition = new RuleLogs();
        	condition.setProjectCode(ruleTest.getProjectCode());
            condition.setRuleflowCode(ruleTest.getModelCode());
//            condition.setBeginDate(ruleTest.getBeginDate());
//            condition.setEndDate(ruleTest.getEndDate());
            List<RuleLogs> logList = ruleLogsService.findList(condition);
            if(logList.size()==0)
            	throw new BizException("", "测试数据不存在，无法进行测试");
            List<RuleTestdata> datalist = new ArrayList<>();
            for (RuleLogs ruleLogs : logList) {
            	RuleTestdata data = new RuleTestdata();
            	data.setProjectCode(ruleTest.getProjectCode());
            	data.setLogRelationid(ruleLogs.getId());
            	data.setRelationId(ruleTest.getId());
            	data.setRuleParam(ruleLogs.getRuleParam());
            	datalist.add(data);
			}
            ruleTestdataService.insertBatch(datalist);
        } catch (Exception e) {
            throw e;
        }
    }

    

    /**
     * 时序执行
     *
     * @param excuteData  执行数据
     * @param projectCode 项目编号
     * @param testId      测试id
     */
    private void excuteTestByTiming(ExcuteData excuteData, String projectCode, String testId,List<Integer> retlist) throws BizException {
        List<String> txParamList = excuteData.getTxParamList();
        String testRuleCode = excuteData.getTestRuleCode();
        String testExcuteVersion = excuteData.getTestExcuteVersion();
        //结果表数据
        List<RuleLogs> list = new ArrayList();
        Map<String, List<RuleResp>> map = new HashMap();
        for (int i = 0; i < txParamList.size(); i++) {
            String ruleflowinfo = testRuleCode + "_" + testExcuteVersion;
           RuleLogs excuteResult = ruleExcuteService.excuteDrl(txParamList.get(i), ruleflowinfo, projectCode);
           excuteResult.setRuleflowid(ruleflowinfo);
           excuteResult.setRuleflowCode(testRuleCode);
           excuteResult.setVersion(testExcuteVersion);
           excuteResult.setEnterPointer(excuteData.getTestId());
           list.add(excuteResult);
        }
        saveLog(list);
        retlist.add(list.size());
    }
    private void saveLog(final List<RuleLogs> ruleLogs) {
//		new Thread(new Runnable() {
//			public void run() {
//				for (RuleLogs ruleLogs2 : ruleLogs) {
//		        	com.tansun.ruledata.entity.RuleLogs log = new com.tansun.ruledata.entity.RuleLogs();
//		        	try {
//		        		BeanUtils.copyProperties(log, ruleLogs2);
//					} catch (IllegalAccessException | InvocationTargetException e) {
//						e.printStackTrace();
//					}
//		        	log.setLogType("2");
//					ruleLogService.saveRuleLog(log);
//				}
//			}
//		}).start();	
    }
    /**
     * 并行任务
     */
    class TestParallelTask extends RecursiveAction {
        //测试数据
        private ExcuteData excuteData;
        //项目编号
        private String projectCode;
        //测试id
        private String testId;
        private List<Integer> list;
        public TestParallelTask(ExcuteData excuteData, String projectCode, String testId,List<Integer> list) {
            this.excuteData = excuteData;
            this.projectCode = projectCode;
            this.testId = testId;
            this.list = list;
        }

        @Override
        protected void compute() {
            Map<String, List<RuleResp>> map = new HashMap();
            List<String> txParamList = excuteData.getTxParamList();
            List<String> rowNoList = excuteData.getRowNoList();
            //超过单任务最大数据量拆分任务
            if (txParamList.size() > TASK_DATA_NUM) {
                int mid = txParamList.size() / 2;
                List<String> txList1 = new ArrayList();
                for (int i = 0; i < mid; i++) {
                    txList1.add(txParamList.get(i));
                }
                List<String> txList2 = new ArrayList();
                for (int i = mid; i < txParamList.size(); i++) {
                    txList2.add(txParamList.get(i));
                }
                //准备子任务执行数据
                ExcuteData excuteData1 = new ExcuteData(excuteData.getTestId(),excuteData.getTestRuleCode(), excuteData.getTestExcuteVersion(), txList1);
                ExcuteData excuteData2 = new ExcuteData(excuteData.getTestId(),excuteData.getTestRuleCode(), excuteData.getTestExcuteVersion(), txList2);
                TestParallelTask task1 = new TestParallelTask(excuteData1, projectCode, testId,list);
                TestParallelTask task2 = new TestParallelTask(excuteData2, projectCode, testId,list);
                invokeAll(task1, task2);
            } else {
                try {
                    System.out.println(Thread.currentThread().getId() + "线程开始时间" + System.currentTimeMillis());
                    excuteTestByTiming(excuteData, projectCode, testId,list);
                    System.out.println(Thread.currentThread().getId() + "线程结束时间" + System.currentTimeMillis());
                } catch (Exception e) {
                    LoggerManager.error("", e, this.getClass());
                }
            }
        }
    }
}
